package top.jacktgq.hsp.nio.groupchat;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Scanner;

/**
 * @Author CandyWall
 * @Date 2020/11/11--20:24
 * @Description NIO群聊客户端
 */
public class GroupChatClient {
    //多路复用器（选择器）
    private Selector selector;

    //监听其他端口的Channel
    private SocketChannel clientChannel;

    //群聊服务器的IP地址
    private static final String HOST = "127.0.0.1";

    //聊天服务器监听的端口号
    private static final int PORT = 6666;

    private String username;

    //完成初始化工作
    public GroupChatClient() {
        try {
            //得到选择器
            selector = Selector.open();

            //获取客户端Channel
            clientChannel = SocketChannel.open();

            //连接服务器
            if (!clientChannel.connect(new InetSocketAddress(HOST, PORT))) {
                while (!clientChannel.finishConnect()) {
                    System.out.println("因为连接需要时间，客户端不会阻塞，可以做其他工作...");
                }
            }

            //将clientChannel设置为非阻塞
            clientChannel.configureBlocking(false);

            //将clientChannel在selector中注册
            clientChannel.register(selector, SelectionKey.OP_READ);

            username = clientChannel.getLocalAddress().toString().substring(1);

            //启动客户端
            start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //向服务器发送消息
    public void sendMsg(String info) {
        try {
            clientChannel.write(ByteBuffer.wrap(info.getBytes()));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //读取服务器发来的消息
    public void readMsg() {
        //获取所有的发送消息的事件
        try {
            //有可以用的通道
            if (selector.select(/*2000*/) > 0) {
                Iterator<SelectionKey> keyIterator = selector.selectedKeys().iterator();
                while (keyIterator.hasNext()) {
                    SelectionKey selectionKey = keyIterator.next();
                    if (selectionKey.isReadable()) {
                        //得到相关的通道
                        SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
                        //得到一个Buffer
                        //ByteBuffer byteBuffer = (ByteBuffer) selectionKey.attachment();
                        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                        int count = socketChannel.read(byteBuffer);
                        if (count > 0) {
                            System.out.println(new String(byteBuffer.array(), "UTF-8"));
                        }
                    }
                    //把当前的key删除，防止重复处理
                    //注：只是从selectedKeys集合中移除了，并没有从Selector中移除，
                    //selector不会自己删除selectedKeys()集合中的selectionKey，
                    //那么如果不人工remove()，将导致下次select()的时候selectedKeys()中
                    //仍有上次轮询留下来的信息，这样必然会出现错误，假设这次轮询时该通道
                    //并没有准备好，却又由于上次轮询未被remove()的原因被认为已经准备好了，这样能不出错吗？
                    keyIterator.remove();
                }
            } /*else {
                System.out.println("没有收到消息");
            }*/

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //启动客户端
    public void start() {
        System.out.println(username + "群聊客户端启动成功...");
        new Thread(() -> {
            while (true) {
                readMsg();
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();

        new Thread(() -> {
            while (true) {
                Scanner scanner = new Scanner(System.in);
                String str = scanner.nextLine();
                sendMsg(str);
            }
        }).start();
    }

    public static void main(String[] args) {
        //创建并启动客户端
        new GroupChatClient();
    }
}
